import Draggable, { DraggableBounds, DraggableData, DraggableEvent } from "react-draggable";
import { Button, Modal, ModalProps } from "antd";
import React, { useEffect, useLayoutEffect, useRef, useState } from "react";
import "./Modal.scss";
import { Resizable } from "react-resizable";
import { CloseOutlined, FullscreenOutlined, FullscreenExitOutlined } from "@ant-design/icons";

interface DraggableModalProps extends ModalProps {
    modalMinWidth?: number;
    width?: number;
    headAction?: React.ReactNode;
    onCancel?: React.MouseEventHandler<HTMLElement>;
    isFull?: boolean;
    onFullChange?: (isFull: boolean) => void;
}

const DraggableModal: React.FC<DraggableModalProps> = props => {
    const [bound, setBound] = useState<DraggableBounds>({ left: 0, top: 0, bottom: 0, right: 0 });
    const draggableRef = useRef<HTMLDivElement>(null);
    const { children, ...other } = props;
    const [resizableWidth, setResizableWidth] = useState<number>(props.width || 0);
    const resizeableSpaceWidth = 5;
    const defaultMinSize = 520;
    const onStart = (event: DraggableEvent, draggableData: DraggableData) => {
        const { clientWidth, clientHeight } = window?.document?.documentElement;
        const targetRect = draggableRef?.current?.getBoundingClientRect();
        setBound({
            left: -targetRect!.left + draggableData?.x,
            right: clientWidth - (targetRect!.right - draggableData?.x) - resizeableSpaceWidth,
            top: -targetRect!.top + draggableData?.y,
            bottom: clientHeight - (targetRect!.bottom - draggableData?.y),
        });
    };

    useLayoutEffect(() => {
        setResizableWidth(props.width || defaultMinSize);
    }, [props.width]);

    const onResize = (e: React.SyntheticEvent<Element, Event>, { size }: any) => {
        if (size.width < (props.modalMinWidth || defaultMinSize)) {
            setResizableWidth(props.modalMinWidth || defaultMinSize);
        } else {
            setResizableWidth(size.width);
        }
    };

    const [isFull, setIsFull] = useState(false);
    const handleFull = (bol: boolean) => {
        setIsFull(bol);
    };
    const [position, setPosition] = useState({ x: 0, y: 0 });

    useEffect(() => {
        setPosition({ x: 0, y: 0 });
    }, [other.open]);

    useEffect(() => {
        if (props.isFull) setIsFull(props.isFull);
    }, [props.isFull]);
    return (
        <Modal
            {...other}
            style={{ top: isFull ? 0 : "20vh" }}
            closable={false}
            title={
                <div className="modalTitle">
                    <div>{props.title}</div>
                    <div>
                        {props.headAction}
                        <Button
                            icon={isFull ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
                            type="text"
                            onClick={() => {
                                handleFull(!isFull);
                                props.onFullChange?.(!isFull);
                                setPosition({ x: 0, y: 0 });
                            }}
                        ></Button>
                        <Button
                            icon={<CloseOutlined />}
                            type="text"
                            onClick={e => {
                                props.onCancel?.(e);
                                props.onFullChange?.(false);
                                setIsFull(false);
                            }}
                        ></Button>
                    </div>
                </div>
            }
            width={isFull ? "100vw" : resizableWidth}
            styles={{ body: { height: isFull ? "calc(100vh - 124px)" : "inherit" }, content: { borderRadius: isFull ? 0 : 8 } }}
            modalRender={modal => (
                <Draggable
                    defaultClassName="modalDraggable"
                    handle={".ant-modal-header"}
                    bounds={bound}
                    onStart={(event, uiData) => onStart(event, uiData)}
                    position={position}
                    onDrag={(_, { x, y }) => setPosition({ x, y })}
                >
                    <div ref={draggableRef} className={"draggable-modal"}>
                        <Resizable width={resizableWidth} height={0} onResize={onResize}>
                            {modal}
                        </Resizable>
                    </div>
                </Draggable>
            )}
        >
            {children}
        </Modal>
    );
};

export default DraggableModal;
